home *** CD-ROM | disk | FTP | other *** search
- // Copyright (c)1995 Ray Dream, Inc. All Rights Reserved.
- /* $Id: COMDefX.cpp 1.7 1997/05/12 19:01:14 damien Exp $ */
-
- ////////////////////////////////////////////////////////////////////////
- // Deformer Example //
- //--------------------------------------------------------------------//
- // Implementation of the Deformer Interface //
- ////////////////////////////////////////////////////////////////////////
-
-
- #ifndef __COMDEFX__
- #include "COMDEFX.h"
- #endif
-
- #ifndef __DEFXDLL__
- #include "DEFXDLL.h"
- #endif
-
- #ifndef __3DCOFAIL__
- #include "3DCoFail.h"
- #endif
-
- #ifndef __I3DSHUTI__
- #include "I3DShUti.h"
- #endif
-
- /*#ifndef __3DBTOOLS__
- #include "3DbTools.h"
- #endif*/
-
- #ifndef __ISHFMESH__
- #include "IShFMesh.h"
- #endif
-
- #undef INTERFACE
- #define INTERFACE Deformer
- // Constructor / Destructor of the C++ Object :
- Deformer::Deformer() {
- fCRef=0; // Reference Counter
-
- // Data initialisation :
- fData.fMinSize = 1.0; // 4 inches
- fData.fExplosionFactor = 0.0;
- fData.fGravityOrNotGravity = FALSE;
- fData.fFloor = 0.0;
- fData.fGravityCoef = 1.0;
-
- fData.fBoundingBox.fMin[0] = 0.0;
- fData.fBoundingBox.fMin[1] = 0.0;
- fData.fBoundingBox.fMin[2] = 0.0;
- fData.fBoundingBox.fMax[0] = 0.0;
- fData.fBoundingBox.fMax[1] = 0.0;
- fData.fBoundingBox.fMax[2] = 0.0;
- }
-
- Deformer::~Deformer() {
- global_count_Obj--;
- }
-
- // IUnknown Interface :
- HRESULT Deformer::QueryInterface(THIS_ REFIID riid,LPVOID* ppvObj) {
- *ppvObj=NULL;
-
- // The Deformer knows the interfaces of the parent Objects
- if (IsEqualIID(riid, IID_IUnknown))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExDeformer2))
- *ppvObj=(LPVOID)(I3DExDeformer2*)this;
- else if (IsEqualIID(riid, IID_I3DExDataExchanger))
- *ppvObj=(LPVOID)(I3DExDataExchanger*)this;
- else if (IsEqualIID(riid, IID_I3DExtension))
- *ppvObj=(LPVOID)(I3DExtension*)this;
-
- // we must add reference if we return an interface
- if (*ppvObj!=NULL) {
- ((LPUNKNOWN)*ppvObj)->AddRef();
- return NOERROR;
- }
- else {
- return ResultFromScode(E_NOINTERFACE);
- }
- }
-
- ULONG Deformer::AddRef(THIS) {
- return fCRef++;
- }
-
- ULONG Deformer::Release(THIS) {
- ULONG UnreleaseObject=fCRef--;
-
- if (fCRef==0)
- delete this; // No reference left, so destroy the object
-
- return UnreleaseObject;
- // local variable used, because fCRef can be destroyed before.
- }
-
- // I3DExtension methods :
- I3DExtension* Deformer::Clone(THIS) {
- Deformer* theClone = new Deformer;
- if (theClone) {
- theClone->AddRef();
- theClone->fData=fData; // copy the DeformerData
- }
- return (I3DExtension*)theClone;
- }
-
- HRESULT Deformer::ShellUtilitiesInit(THIS_ IShUtilities* shellUtilities) {
- InitCoFailure(shellUtilities);
- return NOERROR;
- }
-
- // I3DExDataExchanger methods :
- ExtensionDataMap* Deformer::GetExtensionDataMap(THIS) {
- return NULL;
- }
-
- void* Deformer::GetExtensionDataBuffer(THIS) {
- return &fData; // used by the shell to set the new parameters
- }
-
- HRESULT Deformer::ExtensionDataChanged(THIS) {
- return NOERROR;
- }
-
- HRESULT Deformer::HandleEvent(THIS_ ULONG SourceID) {
- return ResultFromScode(E_NOTIMPL);
- }
-
- short Deformer::GetResID(THIS) {
- return 143; // this is the view ID in the resource file.
- }
-
- // I3DExDeformer methods :
-
- HRESULT Deformer::SetBBox(THIS_ BOX3D *bbox) {
- fData.fBoundingBox=*bbox;
- return NOERROR;
- }
-
- HRESULT Deformer::DeformPoint(THIS_ VECTOR3D* point,VECTOR3D* result) {
- VECTOR3D Translate;
- int i;
- Translate[0] = (*point)[0] * fData.fExplosionFactor;
- Translate[1] = (*point)[1] * fData.fExplosionFactor;
- if (!fData.fGravityOrNotGravity) {
- Translate[2] = (*point)[2] * fData.fExplosionFactor;
- }
- else {
- NUM3D a = 9.8;
- if ((*point)[2]<=fData.fFloor)
- Translate[2]=0.0;
- else {
- Translate[2]=(*point)[2] * fData.fExplosionFactor - fData.fGravityCoef * (fData.fExplosionFactor * fData.fExplosionFactor);
- }
- if ((*point)[2]+Translate[2]<fData.fFloor) {
- Translate[2]=fData.fFloor - (*point)[2];
- }
- }
- for (i=0; i<3; i++) {
- (*result)[i] = (*point)[i] + Translate[i];
- }
- /* (*result)[0] = (*point)[0] * fData.fExplosionFactor;
- (*result)[1] = (*point)[1] * fData.fExplosionFactor;
- (*result)[2] = (*point)[2] * fData.fExplosionFactor; // by Default this deformer change the scale*/
- return NOERROR;
- }
-
- // EVX calls for Mac/EVX case
- extern "C" {
- void OLXIteratorReset(IShIterator *iter);
- void * OLXIteratorNext(IShIterator *iter);
- void * OLXIteratorGetInfo(IShIterator *iter,short index);
- void OLXIteratorDelete(IShIterator *iter);
- }
-
- // Split a Facet between point p1 and p3
- // p1____________ p3
- // \ | /
- // \ f1|f2 /
- // \ | /
- // \ | /
- // \|/
- // p2
- void SplitFacet(const FACET3D *f0,FACET3D *f1,FACET3D *f2,short p1, short p2, short p3) {
- f1->fVertices[0] = f0->fVertices[p1]; // Copy normal/UV/point
- f1->fVertices[1] = f0->fVertices[p2];
- f1->fVertices[2].fVertex[0] = (f0->fVertices[p1].fVertex[0] + f0->fVertices[p3].fVertex[0])/2.0;
- f1->fVertices[2].fVertex[1] = (f0->fVertices[p1].fVertex[1] + f0->fVertices[p3].fVertex[1])/2.0;
- f1->fVertices[2].fVertex[2] = (f0->fVertices[p1].fVertex[2] + f0->fVertices[p3].fVertex[2])/2.0;
- f1->fVertices[2].fNormal[0] = (f0->fVertices[p1].fNormal[0] + f0->fVertices[p3].fNormal[0])/2.0;
- f1->fVertices[2].fNormal[1] = (f0->fVertices[p1].fNormal[1] + f0->fVertices[p3].fNormal[1])/2.0;
- f1->fVertices[2].fNormal[2] = (f0->fVertices[p1].fNormal[2] + f0->fVertices[p3].fNormal[2])/2.0;
- f1->fVertices[2].fUV[0] =(f0->fVertices[p1].fUV[0] + f0->fVertices[p3].fUV[0])/2;
- f1->fVertices[2].fUV[1] =(f0->fVertices[p1].fUV[1] + f0->fVertices[p3].fUV[1])/2;
- f1->fUVSpace = f2->fUVSpace = f0->fUVSpace;
- f2->fVertices[0] = f0->fVertices[p2];
- f2->fVertices[1] = f0->fVertices[p3];
- f2->fVertices[2] = f1->fVertices[2];
- }
-
- // The criteria to split a facet is the longest size on the X axis
- void SplitFacetX(const FACET3D *aFacet,FACET3D *f1,FACET3D *f2) {
- short p1,p2,p3;
- NUM3D dx1,dx2,dx3;
- dx1 = aFacet->fVertices[1].fVertex[0] - aFacet->fVertices[0].fVertex[0];
- dx2 = aFacet->fVertices[2].fVertex[0] - aFacet->fVertices[1].fVertex[0];
- dx3 = aFacet->fVertices[0].fVertex[0] - aFacet->fVertices[2].fVertex[0];
-
- if (dx1<0.0) dx1= -dx1;
- if (dx2<0.0) dx2= -dx2;
- if (dx3<0.0) dx3= -dx3;
-
- if ((dx1>=dx2)&&(dx1>=dx3)) {
- p1=1;p2=2;p3=0;
- // split the facet between p1 and p3
- }
- else if ((dx2>=dx1)&&(dx2>=dx3)) {
- p1=2;p2=0;p3=1;
- // split the facet between p1 and p3
- }
- else {
- p1=0;p2=1;p3=2;
- // split the facet between p1 and p3
- }
- SplitFacet(aFacet,f1,f2,p1,p2,p3);
- }
-
- // The criteria to split a facet is the longest size on the Y axis
- void SplitFacetY(const FACET3D *aFacet,FACET3D *f1,FACET3D *f2) {
- short p1,p2,p3;
- NUM3D dy1,dy2,dy3;
- dy1 = aFacet->fVertices[1].fVertex[1] - aFacet->fVertices[0].fVertex[1];
- dy2 = aFacet->fVertices[2].fVertex[1] - aFacet->fVertices[1].fVertex[1];
- dy3 = aFacet->fVertices[0].fVertex[1] - aFacet->fVertices[2].fVertex[1];
-
- if (dy1<0.0) dy1= -dy1;
- if (dy2<0.0) dy2= -dy2;
- if (dy3<0.0) dy3= -dy3;
-
- if ((dy1>=dy2)&&(dy1>=dy3)) {
- p1=1;p2=2;p3=0;
- // split the facet between p1 and p3
- }
- else if ((dy2>=dy1)&&(dy2>=dy3)) {
- p1=2;p2=0;p3=1;
- // split the facet between p1 and p3
- }
- else {
- p1=0;p2=1;p3=2;
- // split the facet between p1 and p3
- }
- SplitFacet(aFacet,f1,f2,p1,p2,p3);
- }
-
- // The criteria to split a facet is the longest size on the Z axis
- void SplitFacetZ(const FACET3D *aFacet,FACET3D *f1,FACET3D *f2) {
- short p1,p2,p3;
- NUM3D dz1,dz2,dz3;
- dz1 = aFacet->fVertices[1].fVertex[2] - aFacet->fVertices[0].fVertex[2];
- dz2 = aFacet->fVertices[2].fVertex[2] - aFacet->fVertices[1].fVertex[2];
- dz3 = aFacet->fVertices[0].fVertex[2] - aFacet->fVertices[2].fVertex[2];
-
- if (dz1<0.0) dz1= -dz1;
- if (dz2<0.0) dz2= -dz2;
- if (dz3<0.0) dz3= -dz3;
-
- if ((dz1>=dz2)&&(dz1>=dz3)) {
- p1=1;p2=2;p3=0;
- // split the facet between p1 and p3
- }
- else if ((dz2>=dz1)&&(dz2>=dz3)) {
- p1=2;p2=0;p3=1;
- // split the facet between p1 and p3
- }
- else {
- p1=0;p2=1;p3=2;
- // split the facet between p1 and p3
- }
- SplitFacet(aFacet,f1,f2,p1,p2,p3);
- }
-
- // Verify Size of the facet to split it if necessary and move it.
- void Deformer::explodeFacet(const FACET3D *aFacet, IShFacetMeshAccumulator* accu, short level) {
- short i,j;
- NUM3D sx,sy,sz;
- // Calcul size of the Facet
- BOX3D facetbb;
- for(i=0;i<3;i++) facetbb.fMin[i]=facetbb.fMax[i]=aFacet->fVertices[0].fVertex[i];
- for(i=1;i<3;i++) {
- for (j=0;j<3;j++) {
- if (facetbb.fMin[j]>aFacet->fVertices[i].fVertex[j])
- facetbb.fMin[j]=aFacet->fVertices[i].fVertex[j];
- if (facetbb.fMax[j]<aFacet->fVertices[i].fVertex[j])
- facetbb.fMax[j]=aFacet->fVertices[i].fVertex[j];
- }
- }
- sx = facetbb.fMax[0]-facetbb.fMin[0];
- sy = facetbb.fMax[1]-facetbb.fMin[1];
- sz = facetbb.fMax[2]-facetbb.fMin[2];
-
- if (fData.fMinSize<1.0/16.0 || level>SPLITMAX) {
- accu->AddFacet(aFacet);
- }
- else if (sx>fData.fMinSize) {
- FACET3D f1,f2;
- SplitFacetX(aFacet, &f1, &f2);
- explodeFacet(&f1, accu, level+1);
- explodeFacet(&f2, accu, level+1);
- }
- else if (sy>fData.fMinSize) {
- FACET3D f1,f2;
- SplitFacetY(aFacet, &f1, &f2);
- explodeFacet(&f1, accu, level+1);
- explodeFacet(&f2, accu, level+1);
- }
- else if (sz>fData.fMinSize) {
- FACET3D f1,f2;
- SplitFacetZ(aFacet, &f1, &f2);
- explodeFacet(&f1, accu, level+1);
- explodeFacet(&f2, accu, level+1);
- }
- else {
- FACET3D movedFacet=*aFacet;
- moveFacet(&movedFacet);
- accu->AddFacet(&movedFacet);
- }
- }
-
- void Deformer::moveFacet(FACET3D *aFacet) {
- VECTOR3D BaryCentre;
- VECTOR3D Translate;
- int i;
- for (i=0; i<3; i++) {
- BaryCentre[i] = aFacet->fVertices[0].fVertex[i]
- + aFacet->fVertices[1].fVertex[i]
- + aFacet->fVertices[2].fVertex[i];
- BaryCentre[i] /= 3.0;
- }
- Translate[0] = BaryCentre[0] * fData.fExplosionFactor;
- Translate[1] = BaryCentre[1] * fData.fExplosionFactor;
- if (!fData.fGravityOrNotGravity) {
- Translate[2] = BaryCentre[2] * fData.fExplosionFactor;
- }
- else {
- NUM3D a = 9.8;
- if (BaryCentre[2]<=fData.fFloor)
- Translate[2]=0.0;
- else {
- Translate[2]=BaryCentre[2] * fData.fExplosionFactor - fData.fGravityCoef * (fData.fExplosionFactor * fData.fExplosionFactor);
- }
- if (BaryCentre[2]+Translate[2]<fData.fFloor) {
- Translate[2]=fData.fFloor - BaryCentre[2];
- }
- }
- for (i=0; i<3; i++) {
- aFacet->fVertices[0].fVertex[i] += Translate[i];
- aFacet->fVertices[1].fVertex[i] += Translate[i];
- aFacet->fVertices[2].fVertex[i] += Translate[i];
- }
- }
-
- HRESULT Deformer::DeformFacetMesh(NUM3D lod,const FacetMesh &in,FacetMesh &out) {
- IShFacetMeshAccumulator* accu;
- gShellUtilities->CoCreateInstance(CLSID_StandardFacetMeshAccumulator, NULL, CLSCTX_INPROC_SERVER, IID_IShFacetMeshAccumulator, (LPVOID*)&accu);
- IShFacetMeshIterator* iter;
- gShellUtilities->CoCreateInstance(CLSID_StandardFacetMeshIterator, NULL, CLSCTX_INPROC_SERVER, IID_IShFacetMeshIterator, (LPVOID*)&iter);
- iter->Initialize(&in);
- while (iter->Next()) {
- explodeFacet(&iter->GetFacet(), accu);
- }
- iter->Release();
- accu->MakeFacetMesh(out);
- accu->Release();
- return S_OK;
- }
-
- HRESULT Deformer::DeformBBox(const BOX3D &in, BOX3D &out) {
- DeformPoint((VECTOR3D*)&in.fMin, &out.fMin);
- DeformPoint((VECTOR3D*)&in.fMax, &out.fMax);
- return S_OK;
- }
-